#pragma once

#include <cstdint>
#include "Containers/String.h"
#include "Containers/SharedObjectPtr.h"
#include "Containers/WeakObjectPtr.h"

class RObject;

//head of object, it is a piece of memory before object's data
struct WHENGINE_API SObjectHead
{
	SObjectReferenceCounter* RefCounterPtr=nullptr;
	SObjectWeakReferenceCounter* WeakRefCounterPtr=nullptr;

	enum class ELifeState:uint8_t
	{
		//object memory is allocated, but constructor is not called
		WaitingForFirstStageInitialization,

		//the object is created, waiting for FirstTimeInitializeObject()
		//or PostLoadFromAsset()
		WaitingForSecondStageInitialization,
		
		//object is ready to use
		Normal,
		
		//it is being destroyed, do not use it
		Destroying,
	};

	ELifeState State= ELifeState::WaitingForFirstStageInitialization;

	void MarkDestroying()
	{
		State=ELifeState::Destroying;
	}

	bool IsDestroying() const
	{
		return State==ELifeState::Destroying;
	}

	void MarkFirstStageFinished()
	{
		State=ELifeState::WaitingForSecondStageInitialization;
	}

	void MarkSecondStageFinished()
	{
		State=ELifeState::Normal;
	}

	bool IsTotallyInitialized() const
	{
		return State==ELifeState::Normal;
	}

	TSharedObjectPtr<RObject> Owner=nullptr;
	TVector<RObject*> Children; 
	RObject* FindChild(const CString& InNodeName);

	//RawName_NamePostfix make a unique object name in owner's children
	//RawName, for easy human read in editor and serialize
	//NamePostfix make it unique in owner's children
	CString RawName; 
	uint32_t NamePostfix=0;

	CString GetNodeName();
	void SetNodeName(const CString& InNodeName);

	RObject* GetThisObject() const{ return (RObject*)(((uint8_t*)this)+sizeof(SObjectHead)); }
};